<template>
  <view :style="{marginTop:marginTop+'rpx',marginBottom:marginBottom+'rpx'}" class="tui-code__input" @tap="onClick">
    <view :style="{paddingLeft:gap+'rpx',paddingRight:gap+'rpx'}" class="tui-code__input">
      <view v-for="(item,index) in inputArr"
            :key="index"
            :style="{width:width+'rpx',height:height+'rpx',background:background,borderRadius:radius+'rpx',borderColor:activeIndex===index || inputVal[index]?getActiveColor:borderColor,borderTopWidth:(borderType==1?borderWidth:0)+'rpx',borderLeftWidth:(borderType==1?borderWidth:0)+'rpx',borderRightWidth:(borderType==1?borderWidth:0)+'rpx',borderBottomWidth:(borderType==1 || borderType==2?borderWidth:0)+'rpx'}"
            class="tui-cinput__item" @tap="onTap">
        <text
            :style="{width:width+'rpx',height:height+'rpx',fontSize:size+'rpx',lineHeight:height+'rpx',color:color,fontWeight:fontWeight}"
            class="tui-cinput__text">
          {{ password ? (inputVal[index] ? '●' : '') : (inputVal[index] || '') }}
        </text>
        <text :style="{fontSize:size+'rpx',fontWeight:fontWeight}"
              class="tui-cinput__placeholder">
          {{ password ? (inputVal[index] ? '●' : '') : (inputVal[index] || '') }}
        </text>
        <view v-if="cursor && !disabled" :class="{'tui-cinput__cursor-ani':activeIndex===index && focus}"
              :style="{height:cursorHeight+'rpx',background:getCursorColor}" class="tui-cinput__cursor">
        </view>
      </view>
    </view>
    <input :class="{'tui-cinput__ali':ali}" :disabled="disabled" :focus="focus" :maxlength="length"
           :password="password" :type="type" :value="val" class="tui-cinput__hidden" @blur="onBlur"
           @confirm="onConfirm" @focus="onTap" @input="onInput"/>
  </view>
</template>

<script>
export default {
  name: "tuiCodeInput",
  emits: ['complete', 'focus', 'input', 'blur', 'confirm'],
  props: {
    //组件外层左右间距
    gap: {
      type: [Number, String],
      default: 80
    },
    marginTop: {
      type: [Number, String],
      default: 0
    },
    marginBottom: {
      type: [Number, String],
      default: 0
    },
    //初始值，不可超过length长度
    value: {
      type: String,
      default: ''
    },
    //H5不支持动态切换type类型
    type: {
      type: String,
      default: 'text'
    },
    password: {
      type: Boolean,
      default: false
    },
    disabled: {
      type: Boolean,
      default: false
    },
    //获取焦点
    isFocus: {
      type: Boolean,
      default: false
    },
    cursor: {
      type: Boolean,
      default: true
    },
    cursorColor: {
      type: String,
      default: ''
    },
    cursorHeight: {
      type: [Number, String],
      default: 60
    },
    //输入框个数
    length: {
      type: Number,
      default: 4
    },
    width: {
      type: [Number, String],
      default: 108
    },
    height: {
      type: [Number, String],
      default: 108
    },
    background: {
      type: String,
      default: 'transparent'
    },
    //1-显示所有边框 2-只显示底部边框，3-无边框
    borderType: {
      type: [Number, String],
      default: 1
    },
    borderColor: {
      type: String,
      default: '#eaeef1'
    },
    activeColor: {
      type: String,
      default: ''
    },
    borderWidth: {
      type: [Number, String],
      default: 2
    },
    radius: {
      type: [Number, String],
      default: 0
    },
    size: {
      type: [Number, String],
      default: 48
    },
    color: {
      type: String,
      default: '#333'
    },
    fontWeight: {
      type: [Number, String],
      default: 600
    }
  },
  computed: {
    getCursorColor() {
      return this.cursorColor || (uni && uni.$tui && uni.$tui.color.primary) || '#5677fc'
    },
    getActiveColor() {
      return this.activeColor || (uni && uni.$tui && uni.$tui.color.primary) || '#5677fc'
    }
  },
  data() {
    return {
      inputArr: [],
      inputVal: [],
      focus: false,
      activeIndex: -1,
      ali: false,
      val: ''
    };
  },
  watch: {
    length(val) {
      const nums = Number(val);
      if (nums !== this.inputArr.length) {
        this.inputArr = this.getArr(nums)
      }
    },
    value(val) {
      this.focus = true;
      val = val.replace(/\s+/g, "")
      this.getVals(val)
    },
    isFocus(val) {
      this.initFocus(val)
    }
  },
  created() {
    this.inputArr = this.getArr(Number(this.length))
    let val = this.value.replace(/\s+/g, "")
    this.getVals(val, true)
  },
  mounted() {
    this.$nextTick(() => {
      setTimeout(() => {
        this.initFocus(this.isFocus)
      }, 300)
    })
  },
  methods: {
    initFocus(val) {
      if (this.disabled) return;
      if (val && this.activeIndex === -1) {
        this.activeIndex = 0
      }
      if (!this.value && !val) {
        this.activeIndex = -1
      }
      this.$nextTick(() => {
        this.focus = val
      })
    },
    getArr(end) {
      return Array.from(new Array(end + 1).keys()).slice(1);
    },
    getVals(val, init = false) {
      this.val = val
      if (!val) {
        this.inputVal = []
        this.activeIndex = init ? -1 : 0;
      } else {
        let vals = val.split('')
        let arr = []
        this.inputArr.forEach((item, index) => {
          arr.push(vals[index] || '')
        })
        this.inputVal = arr
        const len = vals.length;
        this.activeIndex = len > this.length ? this.length : len;
        if (len === this.length) {
          this.$emit('complete', {
            detail: {
              value: val
            }
          })
          this.focus = false;
          uni.hideKeyboard()
        }
      }
    },
    onTap() {
      if (this.disabled) return;
      this.focus = true;
      if (this.activeIndex === -1) {
        this.activeIndex = 0
      }
      if (this.activeIndex === this.length) {
        this.activeIndex--;
      }
      this.$emit('focus', {})
    },
    onInput(e) {
      let value = e.detail.value;
      value = value.replace(/\s+/g, "")
      this.getVals(value)
      this.$emit('input', {
        detail: {
          value: value
        }
      })
    },
    onBlur(e) {
      let value = e.detail.value;
      value = value.replace(/\s+/g, "")
      this.focus = false
      // #ifdef MP-ALIPAY
      this.ali = false
      // #endif
      if (!value) {
        this.activeIndex = -1;
      }
      this.$emit('blur', {
        detail: {
          value: value
        }
      })
    },
    onConfirm(e) {
      this.focus = false;
      uni.hideKeyboard()
      this.$emit('confirm', e)
    },
    onClick() {
      // #ifdef MP-ALIPAY
      setTimeout(() => {
        this.ali = true
      }, 50)
      // #endif
    },
    clear() {
      this.val = ''
      this.inputVal = []
      this.activeIndex = -1;
      this.$nextTick(() => {
        this.onTap()
      })
    }
  }
}
</script>

<style scoped>
.tui-code__input {
  position: relative;
  /* #ifdef MP-BAIDU */
  max-width: 100%;
  overflow: hidden;
  /* #endif */
}

.tui-code__input {
  /* #ifndef APP-NVUE */
  width: 100%;
  display: flex;
  box-sizing: border-box;
  /* #endif */
  flex: 1;
  flex-direction: row;
  align-items: center;
  justify-content: space-between;
}


.tui-cinput__item {
  /* #ifndef APP-NVUE */
  display: flex;
  box-sizing: border-box;
  /* #endif */
  flex-direction: row;
  justify-content: center;
  align-items: center;
  border-style: solid;
  position: relative;
  overflow: hidden;
}

.tui-cinput__text {
  position: absolute;
  left: 0;
  top: 0;
  flex: 1;
  display: flex;
  flex-direction: row;
  align-items: center;
  justify-content: center;
  text-align: center;
}

.tui-cinput__placeholder {
  text-align: center;
  opacity: 0;
}

.tui-cinput__cursor {
  border-radius: 2px;
  width: 0;
}

.tui-cinput__cursor-ani {
  width: 2px;
  animation: ani_cursor 1s infinite steps(1, start);
}

@keyframes ani_cursor {
  0% {
    opacity: 0;
  }

  50% {
    opacity: 1;
  }

  100% {
    opacity: 0;
  }
}

.tui-cinput__hidden {
  position: absolute;
  left: 0;
  top: 0;
  /* #ifndef MP */
  right: 0;
  bottom: 0;
  /* #endif */
  /* #ifndef MP-WEIXIN || MP-QQ */
  width: 100%;
  height: 100%;
  /* #endif */
  z-index: 2;
  /* #ifdef MP-WEIXIN || MP-QQ || MP-TOUTIAO */
  height: 0;
  width: 0;
  border: none;
  /* #endif */
  margin: 0;
  padding: 0;
  opacity: 0;
  /* #ifdef MP-BAIDU || MP-TOUTIAO */
  font-size: 0;
  /* #endif */

  /* #ifdef MP-BAIDU */
  transform: scaleX(2);
  transform-origin: 100% center;
  /* #endif */
  color: transparent;
}

/* #ifdef MP-ALIPAY */
.tui-cinput__ali {
  height: 0;
  width: 0;
}

/* #endif */
</style>
